home *** CD-ROM | disk | FTP | other *** search
/ Super PC 34 / Super PC 34 (Shareware).iso / spc / UTIL / DJGPP2 / CONTRIB / MAN_PC.ZIP / man_pc / man / man.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-20  |  31.1 KB  |  1,539 lines

  1. static char *rcsid  = "$Id: man.c,v 1.4 1992/10/12 09:59:02 rosenkra Exp $";
  2. static char *version = "man v3.0.2 92/10/11 rosenkra@convex.com";
  3. static char *myname  = "man";
  4.  
  5. /*
  6.  *    man - read on-line documentation
  7.  *
  8.  *    This version uses "manpager" or "less" for paging. It does NOT
  9.  *    call nroff (ie, manpages must be preformatted -- see SUBDIRBASE
  10.  *    macro below).
  11.  *
  12.  *    search order (based on my manpage nomenclature):
  13.  *
  14.  *        man1/*.1[tcgesla]    cmds    util & text,com,graphics,
  15.  *                        edit,shell,lang, archival
  16.  *        man0/*.0        gen
  17.  *        man8/*.8[s]        admin    util & system
  18.  *        man2/*.2[b]        syslib    system & bios
  19.  *        man3/*.3[msvcxl]    libs    C lib & math,stdio,sysV,
  20.  *                        compat,extra,local
  21.  *        man4/*.4[dkvscm]    h/w    gen & disk,keyboard,video,
  22.  *                        sound,chips,memory
  23.  *        man5/*.5        files
  24.  *        man7/*.7        misc
  25.  *        man6/*.6        games
  26.  *
  27.  *    these are seached only if given sections "local", "new", "old":
  28.  *
  29.  *        manl/*.l        local
  30.  *        mann/*.n        new
  31.  *        mano/*.o        old
  32.  */
  33.  
  34. /*
  35.  * $Log: man.c,v $
  36.  * Revision 1.4  1992/10/12  09:59:02  rosenkra
  37.  * basically same as last version (which was premature). fix a couple
  38.  * of bugs.
  39.  *
  40.  * Revision 1.3  1992/10/11  16:21:24  rosenkra
  41.  * this is v3.0.2. it adds a -P alias for -M, ability to source files
  42.  * with either .so manx/file.x or .so file.x; also added was MANSECT
  43.  * env var. help (usage) was beefed up. all reading of env now done in
  44.  * env_inquiry().
  45.  *
  46.  * Revision 1.2  1992/07/27  10:03:38  rosenkra
  47.  * added ability to review all manpages of given name regardless
  48.  * of section (-e). also do env checks before arg parsing.
  49.  *
  50.  * Revision 1.1  1992/07/27  02:03:58  rosenkra
  51.  * Initial revision
  52.  *
  53.  */
  54.  
  55.  
  56.  
  57. #ifdef __hpux
  58. /* HPUX for some reason needs this with <sys/stat.h> */
  59. #define _INCLUDE_POSIX_SOURCE 1
  60. #define unix 1
  61. #endif
  62.  
  63. #include <stdio.h>
  64. #include <ctype.h>
  65. #if defined(unix) || defined(__unix)
  66. #include <sys/types.h>
  67. #include <sys/stat.h>
  68. #include <stdlib.h>
  69. #include <unistd.h>
  70. #include <string.h>
  71. #elif defined(__GNUC__) && defined(MSDOS)
  72. #include <types.h>
  73. #include <stat.h>
  74. #include <stdlib.h>
  75. #include <unistd.h>
  76. #else
  77. #include <sys\types.h>
  78. #include <sys\stat.h>
  79. extern char    *index ();
  80. extern char    *getenv ();
  81. #endif
  82. #ifdef USE_INDEX
  83. #include <strings.h>
  84. #define strchr index
  85. #define strrchr rindex
  86. #endif
  87.  
  88.  
  89. /*
  90.  *    deal with MSDOS
  91.  */
  92. #if defined(unix) || defined(__unix)
  93. #define SLASH_CHR    '/'
  94. #define SLASH_STR    "/"
  95. #else
  96. #define SLASH_CHR    '\\'
  97. #define SLASH_STR    "\\"
  98. #endif
  99.  
  100.  
  101.  
  102. /*
  103.  *    common (default) places. note the patch space...
  104.  */
  105. #if defined(atarist) || defined(MSDOS)
  106. # define MANDIR        "c:\\usr\\man\0\0\0<------MANDIR_patch_space------->\0"
  107. # define BINDIR        "c:\\usr\\bin\0\0\0<------BINDIR_patch_space------->\0"
  108. # define TMPDIR        "c:\\tmp\0\0\0<---------TMPDIR_patch_space--------->\0"
  109. #else
  110. /* assume unix */
  111. # define MANDIR        "/usr/man"
  112. # define BINDIR        "/usr/bin"
  113. # define TMPDIR        "/tmp"
  114. #endif
  115.  
  116.  
  117.  
  118. /*
  119.  *    default pager (we invoke this with system()):
  120.  */
  121. #if defined(unix) || defined(__unix)
  122. # define MORE        "less"        /* could use -m -s also */
  123. #elif defined(atarist)
  124. # define MORE        "less.ttp\0\0\0<--------MORE_patch_space----------->\0"
  125. #elif defined(MSDOS)
  126. # define MORE        "less.exe\0\0\0<--------MORE_patch_space----------->\0"
  127. #endif
  128.  
  129.  
  130. /*
  131.  *    other commands we may run
  132.  */
  133. #ifdef HAS_CAT
  134. # if defined(unix) || defined(__unix)
  135. #  define CAT        "cat -s"    /* for '-' opt, use "cat -s" */
  136. # elif defined(atarist)
  137. #  define CAT        "cat.ttp\0\0\0<---------CAT_patch_space------------>\0"
  138. # elif defined(MSDOS)
  139. #  define CAT        "cat.exe\0\0\0<---------CAT_patch_space------------>\0"
  140. # else
  141. #  undef HAS_CAT
  142. # endif
  143. #endif
  144.  
  145. #ifdef HAS_UL
  146. # if defined(unix) || defined(__unix)
  147. #  define UL        "ul -t dumb"    /* for '- -ul' opt (don't use pager) */
  148. # elif defined(atarist)
  149. #  define UL        "ul.ttp\0\0\0<----------UL_patch_space------------->\0"
  150. # elif defined(MSDOS)
  151. #  define UL        "ul.exe\0\0\0<----------UL_patch_space------------->\0"
  152. # else
  153. #  undef HAS_UL
  154. # endif
  155. #endif
  156.  
  157. #ifdef HAS_APROPOS
  158. # if defined(unix) || defined(__unix)
  159. #  define APROPOS    "apropos"
  160. # elif defined(atarist)
  161. #  define APROPOS    "apropos.ttp\0\0<--------APROPOS_patch_space------->\0"
  162. # elif defined(MSDOS)
  163. #  define APROPOS    "apropos.exe\0\0<--------APROPOS_patch_space------->\0"
  164. # else
  165. #  undef HAS_APROPOS
  166. # endif
  167. #endif
  168.  
  169. #ifdef HAS_WHATIS
  170. # if defined(unix) || defined(__unix)
  171. #  define WHATIS    "whatis"
  172. # elif defined(atarist)
  173. #  define WHATIS    "whatis.ttp\0\0<--------WHATIS_patch_space--------->\0"
  174. # elif defined(MSDOS)
  175. #  define WHATIS    "whatis.ttp\0\0<--------WHATIS_patch_space--------->\0"
  176. # else
  177. #  undef HAS_WHATIS
  178. # endif
  179. #endif
  180.  
  181.  
  182. /*
  183.  *    define sections and subsections. sections are dirs like "man1" and
  184.  *    "cat1". subsections are used in names of manpages within the dir
  185.  *    (eg, "foo.1t").
  186.  */
  187. #define    ALLSECT        "108234576"    /* order to look through sections */
  188.  
  189. #define SUBSEC0        ""        /* subsec to try in each section */
  190. #define    SUBSEC1        "tcgesla"
  191. #define    SUBSEC2        "g"
  192. #define    SUBSEC3        "msvcxl"
  193. #define    SUBSEC4        "dkvscm"
  194. #define SUBSEC5        ""
  195. #define SUBSEC6        ""
  196. #define SUBSEC7        ""
  197. #define    SUBSEC8        "s"
  198. #define SUBSEC9        ""
  199.  
  200. /*
  201.  *    deal with compressed files
  202.  */
  203. #if defined(MSDOS)
  204. #define ZSUFFIX        "Z"        /* for compressed files */
  205. #else
  206. #define ZSUFFIX        ".Z"        /* for compressed files */
  207. #endif
  208. #define ZSWITCH        "-z"    /* for MANPAGER to read compressed file */
  209.  
  210.  
  211. /*
  212.  *    files come from MANPATH/cat*. normally, unix man will first
  213.  *    check for preformatted manpages in /usr/man/cat* dirs. if they
  214.  *    are not found, nroff is run on /usr/man/man* files. with this
  215.  *    man, however, we are assuming that manpages have already been
  216.  *    formatted. by convention, this means that the dirs to search
  217.  *    should be named 'cat[1-8]' and not 'man[1-8]'. if you don't
  218.  *    care about this, make SUBDIRBASE "man".
  219.  */
  220. #define SUBDIRBASE    "cat"
  221.  
  222.  
  223.  
  224. #ifdef dbg
  225. # undef dbg
  226. #endif
  227. #define dbg(x)        if(debugging_G)printf x , fflush(stdout)
  228.  
  229.  
  230. /*
  231.  *    misc macros
  232.  */
  233. #ifdef lastchar
  234. # undef lastchar
  235. #endif
  236. #ifdef plastchar
  237. # undef plastchar
  238. #endif
  239. #define lastchar(s)    ((s)[strlen(s)-1])    /* last char in a string */
  240. #define plastchar(s)    &((s)[strlen(s)-1])    /* ptr to it */
  241.  
  242.  
  243. #define PLEN        256        /* max path length */
  244.  
  245.  
  246.  
  247.  
  248. /*
  249.  *    globals:
  250.  */
  251. #ifdef HAS_UL
  252. int        ul4cat_G  = 0;        /* use ul instead of cat */
  253. #endif
  254. int        every_G = 0;        /* every section */
  255. int        debugging_G = 0;
  256. int        hasmanpager_G = 0;    /* if pager is MANPAGER */
  257. int        usermanpath_G = 0;    /* if -M */
  258. int         nopager_G  = 0;        /* if no pager of any kind */
  259. int        pthpager_G = 0;        /* if pager has a full path */
  260. int        envmansect_G = 0;    /* if MANSECT in env */
  261. char           *manpath_G = 0L;
  262. char        mpbuf[PLEN];
  263. char           *binpath_G = 0L;
  264. char        bpbuf[PLEN];
  265. char           *tmppath_G = 0L;
  266. char        tpbuf[PLEN];
  267. char           *pager_G = 0L;
  268. char        pgbuf[PLEN];
  269. char        cmdbuf_G[512];
  270. int         section_G = 0;        /* section, ascii char */
  271. int         subsec_G = 0;        /* subsection, ascii char */
  272.  
  273.  
  274. /*
  275.  *    set up default search lists. these can be overridden with the env:
  276.  *
  277.  *    setenv MANSECT 108234576,tcgesla,,s,mgbxl,msvcxgl,dkvscm,,,
  278.  */
  279. char           *allsect = ALLSECT;
  280. char           *subsec0 = SUBSEC0;
  281. char           *subsec1 = SUBSEC1;
  282. char           *subsec2 = SUBSEC2;
  283. char           *subsec3 = SUBSEC3;
  284. char           *subsec4 = SUBSEC4;
  285. char           *subsec5 = SUBSEC5;
  286. char           *subsec6 = SUBSEC6;
  287. char           *subsec7 = SUBSEC7;
  288. char           *subsec8 = SUBSEC8;
  289. char           *subsec9 = SUBSEC9;
  290.  
  291. #ifdef LONG_SECT
  292. char           *longsect[] = {"local", "new", "old", "gnu", "paper",
  293.                   "doc", (char *) 0};
  294. #endif
  295.  
  296.  
  297.  
  298. /*
  299.  *    functions:
  300.  */
  301. int        set_section (char *);
  302. int        find_manpage (char *);
  303. int        do_it (char *, int);
  304. char           *so_line (char *);
  305. void        env_inquiry (void);
  306. void        usage (int);
  307.  
  308.  
  309.  
  310. /*------------------------------*/
  311. /*    main            */
  312. /*------------------------------*/
  313. void main (int argc, char *argv[])
  314. {
  315.     int    retcode;
  316.     char  **av;
  317.     int    ac;
  318.  
  319.  
  320.  
  321.     /*
  322.      *   quick scan of args to find debug since we need it first.
  323.      *   note that argc and argv are not changed...
  324.      */
  325.     ac = argc;
  326.     av = argv;
  327.     for (ac--, av++; ac > 0 && **av == '-'; ac--, av++)
  328.     {
  329.         if (*(*av+1) == 'd')
  330.         {
  331.             debugging_G = 1;
  332.             break;
  333.         }
  334.     }
  335.  
  336.  
  337.  
  338.  
  339.     /*
  340.      *   check environment (cmdline overrules things)
  341.      */
  342.     env_inquiry ();
  343.  
  344.  
  345.  
  346.     /*
  347.      *  must have an arg
  348.      */
  349.     argc--, argv++;
  350.     if (argc < 1)
  351.     {
  352.         usage (1);
  353.     }
  354.  
  355.  
  356.  
  357.     /*
  358.      *   parse cmdline. it overrides defaults and environment...
  359.      */
  360.     while (argc > 0 && **argv == '-')
  361.     {
  362.         switch (*(*argv+1))
  363.         {
  364.  
  365.         case 0:                /* use cat (just a "-") */
  366. #ifdef HAS_CAT
  367.             nopager_G++;
  368. #else
  369.             fprintf (stderr, "%s: cat and not supported\n");
  370.             usage (1);
  371. #endif
  372.             break;
  373.  
  374.  
  375.         case 'e':            /* every section */
  376.             every_G++;
  377.             break;
  378.  
  379.  
  380.         case 'P':
  381.         case 'M':            /* reset path (-M path) */
  382.                         /* this is manpath/man[1...] */
  383.             argc--, argv++;
  384.             manpath_G = *argv;
  385.             break;
  386.  
  387.  
  388.         case 'm':            /* reset path (-m path) */
  389.                         /* this is manpath alone */
  390.                         /* use "-m ." for cwd */
  391.             argc--, argv++;
  392.             manpath_G     = *argv;
  393.             usermanpath_G = 1;
  394.             break;
  395.  
  396.  
  397.         case 'u':            /* use ul(1) for cat */
  398. #ifdef HAS_UL
  399.             ul4cat_G++;
  400. #else
  401.             fprintf (stderr, "%s: ul not supported\n");
  402.             usage (1);
  403. #endif
  404.             break;
  405.  
  406.  
  407.         case 's':             /* specific section */
  408.             switch (--argc)
  409.             {
  410.             case 0:            /* Nothing follows -s */
  411.                 fprintf (stderr,
  412.                     "%s: must specify a section with -s\n",
  413.                     myname);
  414.                 usage (1);
  415.  
  416.             case 1:         /* Section, but no man page */
  417.                 fprintf (stderr,
  418.                   "%s: must specify an item from section %s\n",
  419.                     myname, *argv);
  420.                 usage (1);
  421.  
  422.             default: 
  423.                 /*
  424.                  *   if valid section, set_section sets
  425.                  *   section_G
  426.                  */
  427.                 if (set_section (*++argv) == 0)
  428.                 {
  429.                     fprintf (stderr,
  430.                         "%s: unknown section: %s\n",
  431.                         myname, *argv);
  432.                     usage (1);
  433.                 }
  434.                 break;
  435.             }
  436.             break;
  437.  
  438.  
  439.         case 'f':            /* whatis */
  440.         case 'w':
  441. #ifdef HAS_WHATIS
  442. #if defined(__GNUC__) || defined(unix) || defined(__unix)
  443.             strcpy (cmdbuf_G, WHATIS);
  444. #else
  445.             strcpy (cmdbuf_G, binpath_G);
  446.             if (lastchar (cmdbuf_G) != SLASH_CHR)
  447.                 strcat (cmdbuf_G, SLASH_STR);
  448.             strcat (cmdbuf_G, WHATIS);
  449. #endif /*__GNUC__*/
  450.             argc--, argv++;
  451.             while (argc)
  452.             {
  453.                 strcat (cmdbuf_G, " ");
  454.                 strcat (cmdbuf_G, *argv);
  455.                 argc--, argv++;
  456.             }
  457. dbg(("whatis, system (%s)\n",cmdbuf_G));
  458.             retcode = system (cmdbuf_G);
  459.  
  460.             exit (retcode);
  461. #else /*!HAS_WHATIS*/
  462.             fprintf (stderr, "%s: whatis not supported\n");
  463.             usage (1);
  464. #endif /*HAS_WHATIS*/
  465.             break;
  466.             
  467.  
  468.         case 'k':            /* apropos */
  469.         case 'a':
  470. #ifdef HAS_APROPOS
  471.             strcpy (cmdbuf_G, APROPOS);
  472. #if defined(__GNUC__) || defined(unix) || defined(__unix)
  473.             strcpy (cmdbuf_G, APROPOS);
  474. #else
  475.             strcpy (cmdbuf_G, binpath_G);
  476.             if (lastchar (cmdbuf_G) != SLASH_CHR)
  477.                 strcat (cmdbuf_G, SLASH_STR);
  478.             strcat (cmdbuf_G, APROPOS);
  479. #endif /*__GNUC__*/
  480.             argc--, argv++;
  481.             while (argc)
  482.             {
  483.                 strcat (cmdbuf_G, " ");
  484.                 strcat (cmdbuf_G, *argv);
  485.                 argc--, argv++;
  486.             }
  487. dbg(("apropos, system (%s)\n",cmdbuf_G));
  488.             retcode = system (cmdbuf_G);
  489.  
  490.             exit (retcode);
  491. #else /*!HAS_APROPOS*/
  492.             fprintf (stderr, "%s: apropos not supported\n");
  493.             usage (1);
  494. #endif /*HAS_APROPOS*/
  495.             break;
  496.             
  497.  
  498.         case 'h':            /* help */
  499.             usage (0);
  500.             break;
  501.  
  502.  
  503.         case 'd':            /* turn on debugging */
  504.             debugging_G = 1;
  505.             break;
  506.  
  507.  
  508.         case 'v':            /* version */
  509.             printf ("%s\n", version);
  510.             exit (0);
  511.             break;
  512.  
  513.         case '-':
  514.             switch (*(*argv+2))
  515.             {
  516.             case 'v':        /* --version */
  517.                 printf ("%s\n", version);
  518.                 exit (0);
  519.                 break;
  520.  
  521.             case 'h':        /* --help */
  522.                 usage (0);
  523.                 break;
  524.             }
  525.             break;
  526.  
  527.  
  528.         }
  529.         argc--, argv++;
  530.     }
  531.  
  532.  
  533.  
  534.  
  535.     /*
  536.      *   If there are multiple words, no -s seen above, and the first
  537.      *   word is a valid section name, read the subsequent man pages
  538.       *   from that section. set_section will set section_G if *argv is a
  539.       *   bona fide section.
  540.       *
  541.       *   this also should make sure arg is a digit and only <sect>[<sub>]
  542.       *   but will fail on actual manpages named something like "1.1".
  543.       *   hopefully these are non-existent.
  544.      */
  545.     if ((argc > 1) && (section_G == 0)
  546.     && (set_section (*argv) || (isdigit(**argv) && (strlen(*argv) < 3))))
  547.     {
  548.         argc--;
  549.         argv++;
  550.     }
  551.  
  552.  
  553.  
  554.     /*
  555.      *   move to correct directory. no need to move if it is cwd...
  556.      */
  557.     if (strcmp (manpath_G, ".") && (chdir (manpath_G) < 0))
  558.     {
  559.         fprintf (stderr, "%s: can't chdir to %s.\n",
  560.              myname, manpath_G);
  561.         exit (1);
  562.     }
  563.  
  564.  
  565.  
  566.     /*
  567.      *   check if stdout not a tty an no pager.
  568.      */
  569. #if 0
  570.     if (nopager_G == 0 && !isatty (1))
  571.         nopager_G++;
  572. #endif
  573. dbg(("nopager_G = %d, isatty(1) = %d\n", nopager_G, (int) isatty(1)));
  574.  
  575.  
  576.  
  577.     /*
  578.      *   do it for all remaining tokens
  579.      */
  580.     while (argc-- > 0)
  581.     {
  582.         retcode = find_manpage (*argv++);
  583.  
  584.         if (retcode)
  585.         {
  586.             fprintf (stderr, "%s: failed!!!\n", myname);
  587.             exit (retcode);
  588.         }
  589.     }
  590.  
  591.     exit (0);
  592. }
  593.  
  594.  
  595.  
  596.  
  597. /*------------------------------*/
  598. /*    set_section        */
  599. /*------------------------------*/
  600. int set_section (char *cptr)
  601. {
  602.  
  603. /*
  604.  *    routine to set section_G and subsec_G from a given section name,
  605.  *    returning the letter of the section used or a zero if an unfamiliar
  606.  *    keyword is used.
  607.  */
  608.  
  609.     int    sec;
  610.     int    ret;
  611.     int    i;
  612.  
  613.     if (strlen (cptr) > 2)
  614.     {
  615.         /*
  616.          *   section is 3 or more char
  617.          */
  618. #ifdef LONG_SECT
  619.         for (i = 0; longsect[i]; i++)
  620.         {
  621.             if (!strcmp (longsect[i], cptr))
  622.                 return (section_G = (int) (*longsect[i]));
  623.         }
  624. #else
  625.         if (!strcmp (cptr, "local"))
  626.             return ((int) (section_G = 'l'));
  627.         if (!strcmp (cptr, "new"))
  628.             return ((int) (section_G = 'n'));
  629.         if (!strcmp (cptr, "old"))
  630.             return ((int) (section_G = 'o'));
  631. #endif
  632.  
  633.         /* 
  634.          *   If we reach here, none of the special names match,
  635.          *   and we'll return a zero (error) on the other side of
  636.          *   the else. 
  637.          */
  638.         section_G = '\0';
  639.         subsec_G  = '\0';
  640.         ret       = 0;
  641.     }
  642.     else
  643.     {
  644.         /*
  645.          *   section is 2 or less char. subsec could be 0
  646.          */
  647.         section_G = (int) cptr[0];
  648.         subsec_G  = (int) cptr[1];
  649.         ret       = section_G;
  650.  
  651.  
  652.         /*
  653.          *   crude check for legality: section must be 0-8, subsect
  654.          *   must be a letter
  655.          */
  656.         sec = section_G - '0';
  657. /*!!!*/        if (sec < 0 || sec > 9)
  658.             ret = 0;
  659.         if (subsec_G)
  660.         {
  661.             if (!isalpha (subsec_G))
  662.                 ret = 0;
  663.         }
  664.     }
  665.  
  666.     /*
  667.      *   ret is 0 if invalid section, else section number
  668.      */
  669.     return (ret);
  670. }
  671.  
  672.  
  673.  
  674. struct stat     sbuf;
  675.  
  676.  
  677. /*------------------------------*/
  678. /*    find_manpage        */
  679. /*------------------------------*/
  680. int find_manpage (char *name)
  681. {
  682.  
  683. /*
  684.  *    find the manpage file
  685.  */
  686.  
  687.     char        c_sectn;
  688.     char        work[PLEN];
  689.     int         stflag;
  690.     int         last;
  691.     char        seclist[30];
  692.     char        sublist[30];
  693.     char           *psec;
  694.     char           *psub;
  695.     char           *ps;
  696.     char           *cp;
  697.     int        iscompressed = 0;
  698.     int        found = 0;
  699.  
  700.  
  701.  
  702.     /*
  703.      *   set up template (we removed any trailing '/' already)
  704.      *
  705.      *   if usermanpath is set, we read from that dir and don't assume
  706.      *   any "normal" dir structure (-m option). otherwise we do normal
  707.      *   (or -M option).
  708.      */
  709.     if (usermanpath_G)
  710.         sprintf (work,  "%s%s%s.x", manpath_G, SLASH_STR, name);
  711.     else
  712.         sprintf (work,  "%s%s%sx%s%s.x",
  713.              manpath_G, SLASH_STR, SUBDIRBASE, SLASH_STR, name);
  714.  
  715.  
  716.  
  717.     /*
  718.      *   index of last char in template. this should be section.
  719.      *   work[last+1] is subsection, and work[last+2] will be ZSUFFIX
  720.      *   if compressed and we are using MANPAGER.
  721.      */
  722.     last = strlen (work) - 1;
  723. dbg(("template, work = |%s|, last = %d\n", work, last));
  724.  
  725.  
  726.  
  727.     /*
  728.      *   set up list of sections to search. either use section_G or
  729.      *   allsect
  730.      */
  731.     if (section_G)
  732.     {
  733.         seclist[0] = (char) section_G;
  734.         seclist[1] = '\0';
  735.     }
  736.     else
  737.     {
  738.         strcpy (seclist, allsect);
  739.     }
  740.     psec = seclist;
  741.     if (subsec_G)
  742.     {
  743.         sublist[0] = (char) subsec_G;
  744.         sublist[1] = '\0';
  745.         psub = sublist;
  746.     }
  747.     else
  748.         psub = (char *) NULL;
  749. dbg(("psec = |%s|, psub = |%s|\n", psec, (psub ? psub : "NULL")));
  750.  
  751.  
  752.  
  753.     /*
  754.      *   find manx string in template. ps points to the '/'
  755.      */
  756.     if (!usermanpath_G)
  757.     {
  758.         char tmpstringx[PLEN];
  759.         tmpstringx[0] = SLASH_CHR;
  760.         strcpy(&tmpstringx[1], SUBDIRBASE);
  761.         for (ps = work; *ps; ps++)
  762.         {
  763.             if (!strncmp (ps, tmpstringx, 4)
  764.             && *(ps+5) == SLASH_CHR)
  765.                 break;
  766.         }
  767.     }
  768.  
  769.  
  770.  
  771.     /*
  772.      *   loop thru all sections. could be only specified section
  773.      */
  774.     for (c_sectn = *psec; c_sectn; c_sectn = *++psec)
  775.     {
  776.         /*
  777.          *   fill in template: man_/xxx._\0\0 (no sub yet)
  778.          */
  779.         if (!usermanpath_G)
  780.             ps[4] = c_sectn;
  781.  
  782.         work[last]     = c_sectn;
  783.         work[last + 1] = 0;
  784.         work[last + 2] = 0;
  785.         work[last + 3] = 0;
  786.  
  787.  
  788.         /*
  789.          *   if a subsection was specified, skip past this...
  790.          */
  791.         if (subsec_G)
  792.             goto SEARCH;
  793.  
  794.  
  795.         /*
  796.          *   does this file exist?
  797.          */
  798. dbg(("try |%s|...\n", work));
  799.         if ((stflag = stat (work, &sbuf)) >= 0)
  800.         {
  801.             /*
  802.              *   yes...exit this for loop
  803.              */
  804.             if (every_G)
  805.             {
  806.                 /*
  807.                  *   PAGER should support ^C exit. it should
  808.                  *   exit with status 1 in that case (and
  809.                  *   do_it() would also return 1). it is not
  810.                  *   an error, however, to exit this way but
  811.                  *   we return (with 0) so next item will
  812.                  *   be searched.
  813.                  */
  814.                 found++;
  815.                 if (do_it (work, iscompressed))
  816.                     return (0);
  817.                 goto NEXT_LOOP;
  818.             }
  819.             else
  820.                 goto FOUND_ONE;
  821.         }
  822.  
  823.  
  824.         /*
  825.          *   no...try looking for compressed version
  826.          */
  827.         if (hasmanpager_G)
  828.         {
  829. dbg(("not found, try compressed file...\n"));
  830.  
  831. #if 0
  832.             work[last + 1] = ZSUFFIX;
  833.             work[last + 2] = '\0';
  834.             work[last + 3] = '\0';
  835. #endif
  836.             strcpy(&work[last+1], ZSUFFIX);
  837.             
  838. dbg(("try |%s|...\n", work));
  839.             if ((stflag = stat (work, &sbuf)) >= 0)
  840.             {
  841.                 /*
  842.                  *   yes...
  843.                  */
  844.                 iscompressed = 1;
  845.  
  846.                 if (every_G)
  847.                 {
  848.                     found++;
  849.                     if (do_it (work, iscompressed))
  850.                         return (0);
  851.                     goto NEXT_LOOP;
  852.                 }
  853.                 else
  854.                     goto FOUND_ONE;
  855.             }
  856.             work[last + 1] = '\0';    /* reset! */
  857.  
  858. dbg(("not found...\n"));
  859.         }
  860.  
  861.  
  862. SEARCH: ;
  863.         /*
  864.          *   still not found...look for subsections in manx
  865.          *
  866.          *   set up subsect string
  867.          */
  868.         if (subsec_G)
  869.             cp = psub;
  870.         else
  871.         {
  872.             /*
  873.              *   take the default subsections for a section...
  874.              */
  875.             switch (work[last])
  876.             {
  877.             case '0':     cp = subsec0;        break;
  878.             case '1':     cp = subsec1;        break;
  879.             case '2':     cp = subsec2;        break;
  880.             case '3':     cp = subsec3;        break;
  881.             case '4':     cp = subsec4;        break;
  882.             case '5':     cp = subsec5;        break;
  883.             case '6':     cp = subsec6;        break;
  884.             case '7':     cp = subsec7;        break;
  885.             case '8':     cp = subsec8;        break;
  886.             case '9':     cp = subsec9;        break;
  887.             default:     cp = "";        break;
  888.             }
  889.         }
  890. dbg(("not found, try subsect, cp = |%s|\n", cp));
  891.  
  892.  
  893.         /*
  894.          *   cycle thru subsections
  895.          */
  896.         while (*cp)
  897.         {
  898.             /*
  899.              *   do we find one now?
  900.              */
  901.             work[last + 1] = *cp++;
  902.             work[last + 2] = '\0';
  903. dbg(("try |%s|...\n", work));
  904.             if ((stflag = stat (work, &sbuf)) >= 0)
  905.             {
  906.                 /*
  907.                  *   yes...
  908.                  */
  909.                 if (every_G)
  910.                 {
  911.                     found++;
  912.                     if (do_it (work, iscompressed))
  913.                         return (0);
  914.                     goto NEXT_LOOP;
  915.                 }
  916.                 else
  917.                     goto FOUND_ONE;
  918.             }
  919.  
  920.  
  921.             /*
  922.              *   still no...try compressed...
  923.              */
  924.             if (hasmanpager_G)
  925.             {
  926. dbg(("not found, try compressed file...\n"));
  927.  
  928. #if 0
  929.                 work[last + 2] = ZSUFFIX;
  930.                 work[last + 3] = '\0';
  931. #endif
  932.                 strcpy(&work[last+2], ZSUFFIX);
  933.                 
  934. dbg(("try |%s|...\n", work));
  935.                 if ((stflag = stat (work, &sbuf)) >= 0)
  936.                 {
  937.                     /*
  938.                      *   yes...
  939.                      */
  940.                     iscompressed = 1;
  941.                     if (every_G)
  942.                     {
  943.                         found++;
  944.                         if (do_it (work, iscompressed))
  945.                             return (0);
  946.                         goto NEXT_LOOP;
  947.                     }
  948.                     else
  949.                         goto FOUND_ONE;
  950.                 }
  951.                 work[last + 2] = '\0';    /* reset! */
  952.  
  953. dbg(("not found...\n"));
  954.             }
  955.             /* we give up. try next subsection, if any... */
  956.         }
  957.         /* we give up. try next section, if any... */
  958.  
  959. NEXT_LOOP: ;
  960.     }
  961.  
  962.     if (every_G)
  963.     {
  964.         if (found)
  965.             return (0);
  966.         else
  967.             printf ("%s: no manual entry for %s. try man local %s\n",
  968.                 myname, name, name);
  969.     }
  970.     else
  971.     {
  972.         if (section_G == 0)
  973.         printf ("%s: no manual entry for %s. try man local %s\n",
  974.                 myname, name, name);
  975.         else
  976.         printf ("%s: no entry for %s in section %c%c of the manual.\n",
  977.                 myname, name,
  978.                 (char) section_G,
  979.                 (subsec_G ? (char) subsec_G : ' '));
  980.     }
  981.     return (1);
  982.  
  983.  
  984. FOUND_ONE: ;
  985.  
  986. dbg(("Found: %s(%x), iscompressed = %d\n",work,stflag,iscompressed));
  987.  
  988.     return ((int) do_it (work, iscompressed));
  989. }
  990.  
  991.  
  992.  
  993.  
  994. /*------------------------------*/
  995. /*    do_it            */
  996. /*------------------------------*/
  997. int do_it (char *cp, int iscompressed)
  998. {
  999.     char    cmdpath[256];
  1000.     char    cmd[256];
  1001.     char   *so;
  1002.  
  1003.  
  1004.  
  1005.  
  1006.     /*
  1007.      *   open the file, look for ".so file" as first line. use that file
  1008.      *   instead. only one level of this nesting is possible (the
  1009.      *   included file can't include, too). do this only if file not
  1010.      *   compressed!
  1011.      */
  1012. dbg(("enter do_it, cp = |%s|...\n", cp));
  1013.     if (!iscompressed)
  1014.     {
  1015.         so = so_line (cp);
  1016.         if (so)
  1017.         {
  1018.             cp = so;
  1019. dbg(("so_line found something, new cp = |%s|...\n",cp));
  1020.         }
  1021.     }
  1022.  
  1023.  
  1024.     /*
  1025.      *   set up command path (for paging)
  1026.      */
  1027. #if defined(__GNUC__) || defined(unix) || defined(__unix)
  1028.     cmdpath[0] = '\0';
  1029. #else
  1030.     strcpy (cmdpath, binpath_G);
  1031.     if (lastchar (cmdpath) != SLASH_CHR)
  1032.         strcat (cmdpath, SLASH_STR);
  1033. #endif
  1034.     if (!nopager_G)
  1035.     {
  1036.         /*
  1037.          *   use pager. if compressed, add correct switch (note:
  1038.          *   iscompressed set only if hasmanpager is true)
  1039.          */
  1040.         if (iscompressed)
  1041.         {
  1042.             sprintf (cmd, "%s%s %s %s",
  1043.                 (pthpager_G ? "" : cmdpath),
  1044.                 pager_G,
  1045.                 ZSWITCH,
  1046.                 cp);
  1047.         }
  1048.         else
  1049.         {
  1050.             sprintf (cmd, "%s%s %s",
  1051.                 (pthpager_G ? "" : cmdpath),
  1052.                 pager_G,
  1053.                 cp);
  1054.         }
  1055.     }
  1056. #ifdef HAS_UL
  1057.     else if (ul4cat_G)
  1058.     {
  1059.         /*
  1060.          *   use ul rather than cat if no pager
  1061.          */
  1062.         sprintf (cmd, "%s%s %s", cmdpath, UL, cp);
  1063.     }
  1064. #endif
  1065. #ifdef HAS_CAT
  1066.     else
  1067.     {
  1068.         /*
  1069.          *   use cat if no pager
  1070.          */
  1071.         sprintf (cmd, "%s%s %s", cmdpath, CAT, cp);
  1072.     }
  1073. #endif
  1074.  
  1075.     /*
  1076.      *   invoke the pager (or cat or ul)
  1077.      */
  1078. dbg(("system (%s)\n", cmd));
  1079.  
  1080.     return ((int) system (cmd));
  1081. }
  1082.  
  1083.  
  1084.  
  1085.  
  1086. /*------------------------------*/
  1087. /*    so_line            */
  1088. /*------------------------------*/
  1089. char *so_line (char *fname)
  1090. {
  1091.  
  1092. /*
  1093.  *    read first line from found file, looking for ".so " followed by
  1094.  *    alternate sourced file. if found, returns ptr to the new name.
  1095.  *    otherwise, null.
  1096.  *
  1097.  *    the file name should include the path of the subsection, e.g.
  1098.  *    the file for degas.5 (in man5) contains:
  1099.  *
  1100.  *        .so man5/picture.5
  1101.  *
  1102.  *    the rest of the file (man5/degas.5) is ignored.
  1103.  *
  1104.  *    new: now can also handle
  1105.  *
  1106.  *        .so picture.5
  1107.  *
  1108.  *    fname comes in with man5/degas.5 so use the leading path.
  1109.  */
  1110.  
  1111.     static char    buf[256];
  1112.     char        tbuf[256];
  1113.     char           *so;
  1114.     FILE           *stream;
  1115.     char           *ps;
  1116.  
  1117.     so = (char *) 0;
  1118.  
  1119.     if ((stream = fopen (fname, "r")) == (FILE *) 0)
  1120.     {
  1121.         printf ("%s: could not open %s to look for .so\n",
  1122.                 myname, fname);
  1123.         return (so);
  1124.     }
  1125.  
  1126.     /*
  1127.      *   grab first line, delete newline
  1128.      */
  1129.     fgets (buf, 255, stream);
  1130.     fclose (stream);
  1131.     so = buf;
  1132.     while (*++so)
  1133.         ;
  1134.     *--so = '\0';
  1135.  
  1136.     /*
  1137.      *   is it .so?
  1138.      */
  1139.     so = buf;
  1140.     if (!strncmp (so, ".so ", 4))
  1141.     {
  1142.         so += 4;
  1143.         while (*so == ' ' || *so == '\t')
  1144.             so++;
  1145. dbg(("so_line read |%s|\n", so));
  1146.  
  1147.         if ((ps = strrchr (so, '\\')) == (char *) 0
  1148.         &&  (ps = strrchr (so, '/')) == (char *) 0)
  1149.         {
  1150.             /*
  1151.              *   the .so line does not contain manx/name.x so
  1152.              *   use path from fname.
  1153.              */
  1154.             strcpy (tbuf, so);
  1155.             strcpy (so, fname);
  1156.             if (ps = strrchr (so, SLASH_CHR))
  1157.             {
  1158.                 ps++;
  1159.                 strcpy (ps, tbuf);
  1160.             }
  1161.             else if (ps = strrchr (so, '/'))
  1162.             {
  1163.                 ps++;
  1164.                 strcpy (ps, tbuf);
  1165.             }
  1166.         }
  1167.  
  1168. dbg(("so_line returning |%s|\n", so));
  1169.         return (so);
  1170.     }
  1171.     else
  1172.     {
  1173. dbg(("so_line returning NULL\n"));
  1174.  
  1175.         return ((char *) 0);
  1176.     }
  1177. }
  1178.  
  1179.  
  1180.  
  1181. /*------------------------------*/
  1182. /*    env_inquiry        */
  1183. /*------------------------------*/
  1184. void env_inquiry (void)
  1185. {
  1186.  
  1187. /*
  1188.  *    look up things in environment:
  1189.  *
  1190.  *        MANPAGER,PAGER
  1191.  *        TEMP,TMPDIR
  1192.  *        MANPATH,MANDIR
  1193.  *        BINDIR
  1194.  *        MANSECT
  1195.  *
  1196.  *    setenv MANSECT 108234576
  1197.  *    setenv MANSECT 108234576,tcgesla,,s,mgbxl,msvcxgl,dkvscm,,,
  1198.  */
  1199.     char           *ps;
  1200.     char           *pl;
  1201.     char           *pd;
  1202.     static char    sectbuf[256];
  1203.  
  1204.  
  1205.  
  1206.     /*
  1207.      *   alternate pager from environment. if env has variable MANPAGER
  1208.      *   defined, use it as pager (this allows dealing with bold and
  1209.      *   italics in manpage, for example). if not, look for PAGER. if
  1210.      *   neither is set, use default as defined by macro MORE here.
  1211.      */
  1212.     if (pager_G == (char *) NULL)
  1213.     {
  1214.         if ((ps = getenv ("MANPAGER")) != (char *) NULL)
  1215.         {
  1216.             strcpy (pgbuf, ps);
  1217.             pager_G       = pgbuf;
  1218.             hasmanpager_G = 1;
  1219.         }
  1220.         else if ((ps = getenv ("PAGER")) != (char *) NULL)
  1221.         {
  1222.             strcpy (pgbuf, ps);
  1223.             pager_G = pgbuf;
  1224.         }
  1225.         else
  1226.             pager_G = MORE;
  1227.     }
  1228.     if (pager_G && (strchr (pager_G, ':') || strchr (pager_G, SLASH_CHR)))
  1229.         pthpager_G = 1;
  1230. dbg(("pager_G = |%s|, pthpager_G = %d\n",(pager_G ? pager_G : "NULL"), pthpager_G));
  1231.  
  1232.  
  1233.  
  1234.  
  1235.     /*
  1236.      *   place to put temp files, if needed (not needed yet...)
  1237.      */
  1238.     if (tmppath_G == (char *) NULL)
  1239.     {
  1240.         if ((ps = getenv ("TEMP")) != (char *) NULL)
  1241.         {
  1242.             strcpy (tpbuf, ps);
  1243.             tmppath_G = tpbuf;
  1244.         }
  1245.         else if ((ps = getenv ("TMPDIR")) != (char *) NULL)
  1246.         {
  1247.             strcpy (tpbuf, ps);
  1248.             tmppath_G = tpbuf;
  1249.         }
  1250.         else
  1251.             tmppath_G = TMPDIR;
  1252.     }
  1253.     if (tmppath_G && lastchar (tmppath_G) == SLASH_CHR)/* rem trail '/' */
  1254.         lastchar (tmppath_G) = '\0';
  1255. dbg(("tmppath_G = |%s|\n", tmppath_G ? tmppath_G : "NULL"));
  1256.  
  1257.  
  1258.  
  1259.  
  1260.     /*
  1261.      *   where man pages are (e.g. /usr/man)
  1262.      */
  1263.     if (manpath_G == (char *) NULL)
  1264.     {
  1265.         if ((ps = getenv ("MANPATH")) != (char *) NULL)
  1266.         {
  1267.             strcpy (mpbuf, ps);
  1268.             manpath_G = mpbuf;
  1269.         }
  1270.         else if ((ps = getenv ("MANDIR")) != (char *) NULL)
  1271.         {
  1272.             strcpy (mpbuf, ps);
  1273.             manpath_G = mpbuf;
  1274.         }
  1275.         else
  1276.             manpath_G = MANDIR;
  1277.     }
  1278.     if (manpath_G && lastchar (manpath_G) == SLASH_CHR)/* rem trail '/' */
  1279.         lastchar (manpath_G) = '\0';
  1280. dbg(("manpath_G = |%s|\n", manpath_G ? manpath_G : "NULL"));
  1281.  
  1282.  
  1283.  
  1284.  
  1285.     /*
  1286.      *   place to find pagers
  1287.      */
  1288.     if (binpath_G == (char *) NULL)
  1289.     {
  1290.         if ((ps = getenv ("BINDIR")) != (char *) NULL)
  1291.         {
  1292.             strcpy (bpbuf, ps);
  1293.             binpath_G = bpbuf;
  1294.         }
  1295.         else
  1296.             binpath_G = BINDIR;
  1297.     }
  1298.     if (binpath_G && lastchar (binpath_G) == SLASH_CHR)/* rem trail '/' */
  1299.         lastchar (binpath_G) = '\0';
  1300. dbg(("binpath_G = |%s|\n", binpath_G ? binpath_G : "NULL"));
  1301.  
  1302.  
  1303.  
  1304.     /*
  1305.      *   finally, deal with MANSECT. this should be last section
  1306.      *   since this returns.
  1307.      */
  1308.     if ((ps = getenv ("MANSECT")) != (char *) NULL)
  1309.     {
  1310.         strcpy (sectbuf, ps);
  1311. dbg(("MANSECT = |%s|\n", sectbuf));
  1312.         envmansect_G = 1;
  1313.  
  1314.         pl = ps = sectbuf;
  1315.         while (*ps && *ps != ',')    /* find first , */
  1316.             ps++;
  1317.         if (*ps == '\0')        /* if no more list, return */
  1318.             return;
  1319.         *ps++ = '\0';            /* terminate allsect */
  1320.  
  1321.         allsect = pl;
  1322. dbg(("allsect = |%s|\n", allsect));
  1323.  
  1324.         while (*pl)
  1325.         {
  1326. dbg(("for sect %c, ", (int) *pl));
  1327.             pd = ps;
  1328.             switch (*pl)
  1329.             {
  1330.             case '0':    subsec0 = ps;    goto find_comma;
  1331.             case '1':    subsec1 = ps;    goto find_comma;
  1332.             case '2':    subsec2 = ps;    goto find_comma;
  1333.             case '3':    subsec3 = ps;    goto find_comma;
  1334.             case '4':    subsec4 = ps;    goto find_comma;
  1335.             case '5':    subsec5 = ps;    goto find_comma;
  1336.             case '6':    subsec6 = ps;    goto find_comma;
  1337.             case '7':    subsec7 = ps;    goto find_comma;
  1338.             case '8':    subsec8 = ps;    goto find_comma;
  1339.             case '9':    subsec9 = ps;
  1340. find_comma: ;
  1341.                 if (*ps == ',')
  1342.                 {
  1343.                     *ps++ = '\0';
  1344.                     if (*ps == '\0')
  1345.                     {
  1346. dbg(("subsec = empty\n"));
  1347.                         return;
  1348.                     }
  1349. dbg(("subsec = empty\n"));
  1350.                     break;
  1351.                 }
  1352.                 while (*ps && *ps != ',')
  1353.                     ps++;
  1354.                 if (*ps == '\0')
  1355.                 {
  1356. dbg(("subsec = empty\n"));
  1357.                     return;
  1358.                 }
  1359.                 *ps++ = '\0';
  1360. dbg(("subsec = |%s|\n", pd));
  1361.                 break;
  1362.  
  1363.             default:
  1364.                 break;
  1365.             }
  1366.             pl++;
  1367.         }
  1368.     }
  1369. }
  1370.  
  1371.  
  1372. #define FP        fprintf
  1373.  
  1374. /*------------------------------*/
  1375. /*    usage            */
  1376. /*------------------------------*/
  1377. void usage (int excode)
  1378. {
  1379.     char *ps;
  1380.     int i;
  1381.  
  1382. #if 0
  1383. FP (stderr, "Usage: %s [-s sec[sub]] [-M dir | -m dir] [- [-ul]] [-k key] [-f file] [sec[sub]] name\n", myname);
  1384. #endif
  1385.  
  1386.  
  1387. FP (stderr, "\nUsage: %s [options] [sec[sub]] name\n", myname);
  1388.  
  1389.  
  1390. FP (stderr, "Opts:  -s sec[sub]        section/subsect (e.g. 2g)\n");
  1391. FP (stderr, "       -M dir             specify search dir (for man tree)\n");
  1392. FP (stderr, "       -m dir             specify search dir (dir, no tree, eg man -m .)\n");
  1393. #ifdef HAS_CAT
  1394. FP (stderr, "       -                  use cat rather than more or less\n");
  1395. # ifdef HAS_UL
  1396. FP (stderr, "       - -ul              use ul rather than cat\n");
  1397. # endif
  1398. #endif
  1399. #ifdef HAS_APROPOS
  1400. FP (stderr, "       -k key             same as \"apropos keyword\"\n");
  1401. #endif
  1402. #ifdef HAS_WHATIS
  1403. FP (stderr, "       -f file            same as \"whatis file\"\n");
  1404. #endif
  1405.  
  1406.  
  1407. FP (stderr, "Args:  sec                section, alternate for -s\n");
  1408. FP (stderr, "       sub                subsection, alternate for -s\n");
  1409. FP (stderr, "       name               desired entry (command, etc)\n");
  1410.  
  1411.  
  1412. FP (stderr, "Search order:\n");
  1413. if (envmansect_G)
  1414. {
  1415.  for (ps = allsect; *ps; ps++)
  1416.  {
  1417.   switch (*ps)
  1418.   {
  1419.   case '0':
  1420.     FP (stderr, "       %s0%s*.0", SUBDIRBASE, SLASH_STR);
  1421.     if (*subsec0)
  1422.      FP (stderr, "[%s]%s", subsec0, (strlen(subsec0) < 7) ? "\t  " : "  ");
  1423.     else
  1424.      FP (stderr, "\t\t  ");
  1425.     FP (stderr, "general\n");
  1426.       break;
  1427.   case '1':
  1428.     FP (stderr, "       %s1%s*.1", SUBDIRBASE, SLASH_STR);
  1429.     if (*subsec1)
  1430.      FP (stderr, "[%s]%s", subsec1, (strlen(subsec1) < 7) ? "\t  " : "  ");
  1431.     else
  1432.      FP (stderr, "\t\t  ");
  1433.     FP (stderr, "commands\n");
  1434.       break;
  1435.   case '2':
  1436.     FP (stderr, "       %s2%s*.2", SUBDIRBASE, SLASH_STR);
  1437.     if (*subsec2)
  1438.      FP (stderr, "[%s]%s", subsec2, (strlen(subsec2) < 7) ? "\t  " : "  ");
  1439.     else
  1440.      FP (stderr, "\t\t  ");
  1441.     FP (stderr, "system calls\n");
  1442.       break;
  1443.   case '3':
  1444.     FP (stderr, "       %s3%s*.3", SUBDIRBASE, SLASH_STR);
  1445.     if (*subsec3)
  1446.      FP (stderr, "[%s]%s", subsec3, (strlen(subsec3) < 7) ? "\t  " : "  ");
  1447.     else
  1448.      FP (stderr, "\t\t  ");
  1449.     FP (stderr, "library calls\n");
  1450.       break;
  1451.   case '4':
  1452.     FP (stderr, "       %s4%s*.4", SUBDIRBASE, SLASH_STR);
  1453.     if (*subsec4)
  1454.      FP (stderr, "[%s]%s", subsec4, (strlen(subsec4) < 7) ? "\t  " : "  ");
  1455.     else
  1456.      FP (stderr, "\t\t  ");
  1457.     FP (stderr, "hardware\n");
  1458.       break;
  1459.   case '5':
  1460.     FP (stderr, "       %s5%s*.5", SUBDIRBASE, SLASH_STR);
  1461.     if (*subsec5)
  1462.      FP (stderr, "[%s]%s", subsec5, (strlen(subsec5) < 7) ? "\t  " : "  ");
  1463.     else
  1464.      FP (stderr, "\t\t  ");
  1465.     FP (stderr, "special files\n");
  1466.       break;
  1467.   case '6':
  1468.     FP (stderr, "       %s6%s*.6", SUBDIRBASE, SLASH_STR);
  1469.     if (*subsec6)
  1470.      FP (stderr, "[%s]%s", subsec6, (strlen(subsec6) < 7) ? "\t  " : "  ");
  1471.     else
  1472.      FP (stderr, "\t\t  ");
  1473.     FP (stderr, "games\n");
  1474.       break;
  1475.   case '7':
  1476.     FP (stderr, "       %s7%s*.7", SUBDIRBASE, SLASH_STR);
  1477.     if (*subsec7)
  1478.      FP (stderr, "[%s]%s", subsec7, (strlen(subsec7) < 7) ? "\t  " : "  ");
  1479.     else
  1480.      FP (stderr, "\t\t  ");
  1481.     FP (stderr, "misc\n");
  1482.       break;
  1483.   case '8':
  1484.     FP (stderr, "       %s8%s*.8", SUBDIRBASE, SLASH_STR);
  1485.     if (*subsec8)
  1486.      FP (stderr, "[%s]%s", subsec8, (strlen(subsec8) < 7) ? "\t  " : "  ");
  1487.     else
  1488.      FP (stderr, "\t\t  ");
  1489.     FP (stderr, "admin commands\n");
  1490.       break;
  1491.   case '9':
  1492.     FP (stderr, "       %s9%s*.9", SUBDIRBASE, SLASH_STR);
  1493.     if (*subsec9)
  1494.      FP (stderr, "[%s]%s", subsec9, (strlen(subsec9) < 7) ? "\t  " : "  ");
  1495.     else
  1496.      FP (stderr, "\t\t  ");
  1497.     FP (stderr, "other\n");
  1498.       break;
  1499.   }
  1500.  }
  1501. }
  1502. else
  1503. {
  1504. FP (stderr, "       %s1%s*.1[tcgesla] cmds (util & text,com,graph,edit,shell,lang,archive)\n", SUBDIRBASE, SLASH_STR);
  1505. FP (stderr, "       %s0%s*.0          general\n", SUBDIRBASE, SLASH_STR);
  1506. FP (stderr, "       %s8%s*.8[s]       admin (util & system)\n", SUBDIRBASE, SLASH_STR);
  1507. FP (stderr, "       %s2%s*.2[b]       syslib (unix & bios)\n", SUBDIRBASE,SLASH_STR);
  1508. FP (stderr, "       %s3%s*.3[msvcxl]  libs (C lib & math,stdio,sysV,compat,misc,local)\n", SUBDIRBASE, SLASH_STR);
  1509. FP (stderr, "       %s4%s*.4[dkvscm]  h/w (gen & disk,keyboard,video,sound,chips,memory)\n", SUBDIRBASE, SLASH_STR);
  1510. FP (stderr, "       %s5%s*.5          special files\n", SUBDIRBASE,SLASH_STR);
  1511. FP (stderr, "       %s7%s*.7          misc\n", SUBDIRBASE, SLASH_STR);
  1512. FP (stderr, "       %s6%s*.6          games\n", SUBDIRBASE, SLASH_STR);
  1513. }
  1514.  
  1515.  
  1516. #ifdef LONG_SECT
  1517. FP (stderr, "Other sections:          ");
  1518. for (i = 0; i < 10; i++)
  1519. {
  1520.  if (longsect[i] == (char *) NULL)
  1521.   break;
  1522.  FP (stderr, "%s", longsect[i]);
  1523.  if (longsect[i+1])
  1524.   FP (stderr, ",");
  1525. }
  1526. FP (stderr, "\n");
  1527. #else
  1528. FP (stderr, "Other sections:          local,new,old\n");
  1529. #endif
  1530.  
  1531.  
  1532. FP (stderr, "Environment:             MANPAGER,PAGER,MANPATH,MANSECT,BINDIR,TMPDIR\n");
  1533.  
  1534.  
  1535. exit (excode);
  1536. }
  1537.  
  1538.  
  1539.